package com.xhwl.centiotdata.handler.eesd.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xhwl.centiotdata.handler.eesd.EesdFactory;
import com.xhwl.centiotdata.handler.eesd.EesdHandler;
import com.xhwl.centiotdata.pojo.dto.eesd.EesdConfigDTO;
import com.xhwl.centiotdata.pojo.enums.device.DeviceProductCategoryEnum;
import com.xhwl.centiotdata.pojo.enums.eesd.EesdMethodEnum;
import com.xhwl.centiotdata.service.cent.IEesdCentService;
import com.xhwl.centiotdata.service.integrateconfig.EESDSupplierConfig;
import com.xhwl.centiotdata.suppliersystem.eesd.kede.KeDeApiHandler;
import com.xhwl.common.dto.cent.eesd.RechargeRecordDTO;
import com.xhwl.common.dto.cent.energy.EesdElectricDetailDTO;
import com.xhwl.common.pojo.ResultJson;
import com.xhwl.common.pojo.cent.device.DeviceProjSupplierCategory;
import com.xhwl.common.pojo.cent.eesd.EnergyBillingDetailEntity;
import com.xhwl.common.utils.LocalDateTimeUtils;
import com.xhwl.common.utils.PageOutVO;
import com.xhwl.common.vo.cent.energy.EnergyDeviceViewVO;
import com.xhwl.common.vo.cent.energy.EnergyListVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author tangwei
 * @description 科德水电系统
 * @create 2023-05-04 10:22
 */
@Slf4j
@Service
public class EesdKeDeHandler extends EesdHandler {

    @Autowired
    private KeDeApiHandler keDeApiHandler;

    @Autowired
    private EESDSupplierConfig supplierConfig;

    @Autowired
    private IEesdCentService energyService;

    @Autowired
    IEesdCentService iEesdCentService;

    /**
     * 99 - 科德水电系统
     */
    @Override
    public void afterPropertiesSet() {
        EesdFactory.register(EesdMethodEnum.KEDE.getId(), this);
    }

    @Override
    public ResultJson rechargeElectricityAndWater(EesdConfigDTO configDTO, RechargeRecordDTO dto) {
        DeviceProjSupplierCategory supplierCategory = getSupplierConfig(dto.getProductId(), dto.getProjectId());
        return keDeApiHandler.rechargeElectricityAndWater(supplierCategory, dto);
    }

    @Override
    public void pullRecord(EesdConfigDTO configDTO) {
        Integer productId = EesdMethodEnum.KEDE.getId();
        Integer projectId = configDTO.getProjectId();
        DeviceProjSupplierCategory supplierConfig = getSupplierConfig(productId, projectId);
        if (Objects.isNull(supplierConfig)) {
            log.info("获取的科德子系统能耗集成配置为空=>{}", projectId);
        }
        List<EesdElectricDetailDTO> dtoList = keDeApiHandler.pullRecord(supplierConfig);
        if (!CollectionUtils.isEmpty(dtoList)) {
            log.info("获取的能耗水电表累计量记录为=>{}", dtoList);
            iEesdCentService.baDeviceDetailSync(dtoList);
        }
    }

    @Override
    public void pullKeDeElectricityPaymentData(DeviceProjSupplierCategory config, Integer intervalDay, String deviceNo) {
        if (Objects.isNull(config)) {
            return ;
        }
        // 拉取电表充值记录
        List<EnergyBillingDetailEntity> energyBillingDetailEntities = keDeApiHandler.pullKeDeElectricityData(config, intervalDay, deviceNo);
        if (CollectionUtils.isEmpty(energyBillingDetailEntities)) {
            return;
        }
        // 处理电表充值记录
        List<EnergyBillingDetailEntity> resultList = handlePaymentData(config, energyBillingDetailEntities);
        // 转存电表充值记录
        energyService.syncBillingRecord(JSON.toJSONString(resultList));
    }

    @Override
    public ResultJson controlElectricityMeter(DeviceProjSupplierCategory config, String deviceNo, Integer cutoffState) {
        return keDeApiHandler.controlElectricityMeter(config, deviceNo, cutoffState);
    }

    @Override
    public void ownAlarmPush(DeviceProjSupplierCategory config, JSONObject params) {
        keDeApiHandler.ownAlarmPush(config,params);
    }

    @Override
    public void pullKeDeWaterPaymentData(DeviceProjSupplierCategory config, Integer intervalDay, String deviceNo) {
        if (Objects.isNull(config)) {
            return;
        }
        // 拉取水表充值记录
        List<EnergyBillingDetailEntity> energyBillingDetailEntities = keDeApiHandler.pullKeDeWaterData(config, intervalDay, deviceNo);
        if (CollectionUtils.isEmpty(energyBillingDetailEntities)) {
            return;
        }
        // 处理水表充值记录
        List<EnergyBillingDetailEntity> resultList = handlePaymentData(config, energyBillingDetailEntities);
        // 转存水表充值记录
        energyService.syncBillingRecord(JSON.toJSONString(resultList));
    }

    private List<EnergyBillingDetailEntity> handlePaymentData(DeviceProjSupplierCategory config, List<EnergyBillingDetailEntity> list) {
        List<EnergyBillingDetailEntity> mergeList = new ArrayList<>(list.size());
        Map<String, List<EnergyBillingDetailEntity>> map = list.stream().collect(Collectors.groupingBy(EnergyBillingDetailEntity::getDeviceNo));
        map.keySet().forEach(item -> {
            EnergyBillingDetailEntity entity = new EnergyBillingDetailEntity();
            List<EnergyBillingDetailEntity> entities = map.get(item);
            // 获取最新一次充值记录
            entities.sort(Comparator.comparing(EnergyBillingDetailEntity::getTime).reversed());
            EnergyBillingDetailEntity latestRecord = entities.get(0);
            BeanUtils.copyProperties(latestRecord, entity);
            // 统一处理时间格式
            entity.setTime(getPayTime(latestRecord.getTime()));
            // 当天充值金额
            BigDecimal totalAmount = entities.stream().map(EnergyBillingDetailEntity::getRechargeAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            entity.setRechargeAmount(totalAmount);
            // 当天剩余金额 = 最新一条记录电/水剩余金额
            entity.setBalance(latestRecord.getBalance());
            // 当天余电/水量 = 最新一条记录余电/水量
            if (Objects.nonNull(latestRecord.getRemaining())) {
                entity.setRemaining(latestRecord.getRemaining());
            }
            // 获取当日累计用量
            if (Objects.isNull(latestRecord.getAccumulativeConsumption())) {
                BigDecimal consumption = keDeApiHandler.getWaterOrElectricityReadInfo(config, latestRecord);
                if (Objects.nonNull(consumption)) {
                    entity.setAccumulativeConsumption(consumption);
                }
            }
            mergeList.add(entity);
        });
        return mergeList;
    }

    private LocalDateTime getPayTime(LocalDateTime time) {
        DateTimeFormatter ft1 = DateTimeFormatter.ofPattern(LocalDateTimeUtils.YEAR_MONTH_DAY);
        String timeStr = time.format(ft1) + " 12:00:00";
        DateTimeFormatter ft2 = DateTimeFormatter.ofPattern(LocalDateTimeUtils.DATE_TIME);
        return LocalDateTime.parse(timeStr, ft2);
    }

    private void handleBillingData(List<EnergyBillingDetailEntity> list) {
        // 查询水电仪表列表
        EnergyBillingDetailEntity entity = list.get(0);
        EnergyListVO energyListVO = new EnergyListVO();
        energyListVO.setProjectId(entity.getProjectId());
        energyListVO.setDeviceType(entity.getDeviceType());
        ResultJson resultJson = energyService.deviceList(energyListVO, null);
        Object object = resultJson.getResult();
        PageOutVO<EnergyDeviceViewVO> pageOutVO = JSON.parseObject(JSON.toJSONString(object), PageOutVO.class);
        List<EnergyDeviceViewVO> energyDeviceViewVOS = pageOutVO.getList();
        log.info("获取的水电表信息==>{}", energyDeviceViewVOS);
        if (CollectionUtils.isEmpty(energyDeviceViewVOS)) {
            return;
        }
        // 封装租户map和计量区域map
        Map<String, String> deviceMeteringAreaNameMap = new HashMap<>(energyDeviceViewVOS.size());
        Map<String, String> tenantNameMap = new HashMap<>(energyDeviceViewVOS.size());
        energyDeviceViewVOS.forEach(vo -> {
            List<EnergyDeviceViewVO.CountAreaVO> countAreaVOList = vo.getCountAreas();
            // 计量区域map
            if (!CollectionUtils.isEmpty(countAreaVOList)) {
                StringBuilder builder = new StringBuilder();
                countAreaVOList.forEach(item -> {
                    if (StringUtils.isNotBlank(item.getDeviceMeteringAreaName())) {
                        builder.append(item.getDeviceMeteringAreaName()).append(",");
                    }
                });
                String areaName = builder.toString();
                deviceMeteringAreaNameMap.put(vo.getDeviceNo(), areaName.substring(0, areaName.length() - 1));
            }
            // 租户map
            List<EnergyDeviceViewVO.TenantVO> tenantVOList = vo.getTenants();
            if (!CollectionUtils.isEmpty(tenantVOList)) {
                StringBuilder builder = new StringBuilder();
                tenantVOList.forEach(item -> {
                    if (StringUtils.isNotBlank(item.getTenantName())) {
                        builder.append(item.getTenantName()).append(",");
                    }
                });
                String tenantName = builder.toString();
                tenantNameMap.put(vo.getDeviceNo(), tenantName.substring(0, tenantName.length() - 1));
            }
        });
        // 处理业主用户名称和计量区域名称
        list.forEach(obj -> {
            if (deviceMeteringAreaNameMap.containsKey(obj.getDeviceNo())) {
                obj.setDeviceMeteringAreaName(deviceMeteringAreaNameMap.get(obj.getDeviceNo()));
            }
            if (tenantNameMap.containsKey(obj.getDeviceNo())) {
                obj.setOwnerName(tenantNameMap.get(obj.getDeviceNo()));
            }
        });
    }


    private DeviceProjSupplierCategory getSupplierConfig(Integer productId, Integer projectId) {
        return supplierConfig.getIntegrationConfig(DeviceProductCategoryEnum.EESD.getId()).stream()
                .filter(c -> Objects.equals(c.getProductId(), productId) && !c.getProperties().isEmpty())
                .filter(c -> Objects.equals(c.getProjectId(), projectId)).collect(Collectors.toList()).get(0);
    }
}
